package com.ndp.fb.scheduler.annotation;

import com.ndp.fb.redis.api.RedisClient;
import com.ndp.fb.util.StringUtil;
import com.ndp.fb.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 调度可被执行的共享锁，如果没有获得锁，则调度不能执行
 * Created by hunk.qin on 2015/7/17.
 */
@Component
public class ScheduleLock  {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    public RedisClient redisClient;

    @Autowired
    CronScheduledAnnoationBeanPostProcessor postProcessor;


    public   boolean haslock=false;

    private static final String LOCK_KEY="scheduler_key";

    private static final long LOCK_OUTTIME=60*1000;

    private String owner= UUID.get();

    @PostConstruct
    public  void initLock(){
        String lockobj= owner+","+System.currentTimeMillis();
        haslock=redisClient.setNx(LOCK_KEY, lockobj);
        }

    public void releaseLock(){
        redisClient.delete(LOCK_KEY);
    }

    public void daemon() {
            String key=(String)redisClient.get(LOCK_KEY);
            logger.info("获得当前的key值为:"+key);
            String currentkey=null;
            long   currentkeytime=0L;
            if(StringUtil.isNotEmpty(key)){
                String [] keytimes=key.split(",");
                currentkey=keytimes[0];
                currentkeytime=Long.valueOf(keytimes[1]);
            }
            if(StringUtil.isNotEmpty(currentkey)){
                logger.info("当前key不为空，检查是否自己持有的key");
                if(currentkey.equals(owner)){
                    logger.info("是自己持有的key，更新时间戳");
                    redisClient.set(LOCK_KEY,owner+","+System.currentTimeMillis());
                }else{
                    logger.info(" 不是自己持有的key，检查key是否过期");
                    if((System.currentTimeMillis()-currentkeytime)>LOCK_OUTTIME){
                        logger.info("当前key 已经过期，进行回收，尝试获取新的key，超时时间："+(System.currentTimeMillis()-currentkeytime));
                        String oldkey =(String)redisClient.getSet(LOCK_KEY,owner+","+System.currentTimeMillis());
                        if(oldkey.equals(key)){
                            logger.info("当前节点放入新的key，检查替换回来的key和之前的一致，获得key：置换前的key："+oldkey);
                            haslock=true;
                            registerTask();
                        }else {
                            logger.info("当前节点放入新的key，检查替换回来的key和之前的不一致，key别的节点获得：当前的key："+oldkey);
                        }
                    }else{
                        logger.info("当前锁没有过期，更新时间：{}秒前",(System.currentTimeMillis()-currentkeytime)/1000);
                    }
                }
            }else{
                haslock=redisClient.setNx(LOCK_KEY, owner+","+System.currentTimeMillis());
                if(haslock){
                    logger.info("当前key已经被删除，当前节点获得到key，开始注册调度，并开始写入心跳：");
                    registerTask();
                }
            }

    }

    void registerTask(){
        logger.info("scheduled 获得了锁，开始注册服务");
        postProcessor.reRegisterDestroy();
        for (Object o : postProcessor.objectmap.values()) {
            postProcessor.getObject(o,o.getClass().getName());
        }
        postProcessor.reRegister();
    }

}
